package dyl.sys.filter;

import java.math.BigDecimal;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import com.alibaba.fastjson.JSONObject;

import dyl.common.bean.R;
import dyl.common.util.AuthUtil;
import dyl.sys.action.BaseAction;
import dyl.sys.bean.SysUser;
import dyl.sys.init.AuthCache;


/**
 * 拦截器,用于拦截权限
 * @author dyl
 *
 */
public class AuthInterceptor implements HandlerInterceptor {
	protected Log log = LogFactory.getLog(getClass());
	
	/**
	 * 权限注入
	 */
	@Override
	public boolean preHandle(HttpServletRequest request,HttpServletResponse response, Object handler) throws Exception {
		HandlerMethod handlerMethod = (HandlerMethod)handler;
		BaseAction  baseAction  =(BaseAction)handlerMethod.getBean();
		SysUser u = baseAction.getSysUser(request);
		if(u.isAdmin())return true;
		String  methodName =  handlerMethod.getMethod().getName();//方法名称
		String actionName = handlerMethod.getBeanType().getName();//actionName
		actionName = actionName.substring(actionName.lastIndexOf(".")+1, actionName.length());
		actionName = actionName.substring(0,1).toLowerCase()+actionName.substring(1,actionName.length());
		
		BigDecimal menuId = AuthCache.acitonMenuIdMap.get(actionName);//获取菜单Id
		BigDecimal kindId = AuthCache.methodAuthKindMap.get(methodName);//获取该方法需要判断的种类Id
		if(menuId==null){//该Menu未配置actionClass
			log.warn(actionName + "action,"+methodName+"没有配置actionClass!");
			return true;
		}
		if(kindId==null){//该方法没有配置权限
			log.warn(actionName + "action,"+methodName+"方法没有配置权限!");
			return true;
		}
		if(!AuthUtil.hasPermission(menuId, kindId, u.getMenuAuthMap())){//判断是否有权限
			response.getWriter().print(JSONObject.toJSON(new R(false,"无此权限")));
			return false;
		}
		request.setAttribute("menuId", menuId);
		return true;
	}
	/**
	 * 这个方法只会在当前这个Interceptor的preHandle方法返回值为true的时候才会执行。postHandle是进行处理器拦截用的，它的执行时间是在处理器进行处理之
	 * 后，也就是在Controller的方法调用之后执行，但是它会在DispatcherServlet进行视图的渲染之前执行，也就是说在这个方法中你可以对ModelAndView进行操
	 * 作。这个方法的链式结构跟正常访问的方向是相反的，也就是说先声明的Interceptor拦截器该方法反而会后调用，这跟Struts2里面的拦截器的执行过程有点像，
	 * 只是Struts2里面的intercept方法中要手动的调用ActionInvocation的invoke方法，Struts2中调用ActionInvocation的invoke方法就是调用下一个Interceptor
	 * 或者是调用action，然后要在Interceptor之前调用的内容都写在调用invoke之前，要在Interceptor之后调用的内容都写在调用invoke方法之后。
	 */
	@Override
	public void postHandle(HttpServletRequest request,HttpServletResponse response, Object handler,ModelAndView modelAndView) throws Exception {
	}

	/**
	 * 该方法也是需要当前对应的Interceptor的preHandle方法的返回值为true时才会执行。该方法将在整个请求完成之后，也就是DispatcherServlet渲染了视图执行，
	 * 这个方法的主要作用是用于清理资源的，当然这个方法也只能在当前这个Interceptor的preHandle方法的返回值为true时才会执行。
	 */
	@Override
	public void afterCompletion(HttpServletRequest request,
			HttpServletResponse response, Object handler, Exception ex)throws Exception {
	}
}
